﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MLForgeSharp.Models.SupervisedLearningModels.Nearest
{
    /// <summary>
    /// k近邻分类
    /// </summary>
    public class kNNModel
    {
        private double[][] trainingData; // 训练数据
        private double[] trainingLabels; // 训练标签
        private int k; // k 值

        public kNNModel(int k = 3)
        {
            this.k = k;
        }

        // 训练模型（kNN 的训练只是保存数据）
        public void Train(double[][] data, double[] labels)
        {
            this.trainingData = data;
            this.trainingLabels = labels;
        }

        // 计算欧氏距离
        private double EuclideanDistance(double[] a, double[] b)
        {
            double sum = 0.0;
            for (int i = 0; i < a.Length; i++)
            {
                sum += Math.Pow(a[i] - b[i], 2);
            }
            return Math.Sqrt(sum);
        }

        // 预测
        public double Predict(double[] features)
        {
            // 计算新样本与所有训练样本的距离
            double[] distances = new double[trainingData.Length];
            for (int i = 0; i < trainingData.Length; i++)
            {
                distances[i] = EuclideanDistance(features, trainingData[i]);
            }

            // 找到距离最小的k个样本的索引
            int[] nearestIndices = new int[k];
            for (int i = 0; i < k; i++)
            {
                double minDistance = double.MaxValue;
                int minIndex = -1;

                for (int j = 0; j < distances.Length; j++)
                {
                    if (distances[j] < minDistance)
                    {
                        minDistance = distances[j];
                        minIndex = j;
                    }
                }

                nearestIndices[i] = minIndex;
                distances[minIndex] = double.MaxValue; // 避免重复选择
            }

            // 计算 k 个最近邻的平均值（回归任务）
            double sum = 0.0;
            for (int i = 0; i < k; i++)
            {
                sum += trainingLabels[nearestIndices[i]];
            }
            return sum / k;
        }
    }

    // 示例程序
    public class kNNModelExample
    {
        public kNNModelExample()
        {
            // 示例数据
            double[][] data = new double[][]
        {
            new double[] { 1.0, 2.0 },
            new double[] { 1.1, 2.1 },
            new double[] { 1.2, 2.2 },
            new double[] { 1.3, 2.3 },
            new double[] { 10.0, 10.0 },
            new double[] { 10.1, 10.1 }
        };

            double[] labels = { 0.0, 0.0, 0.0, 0.0, 1.0, 1.0 }; // 目标值

            // 创建模型
            kNNModel model = new kNNModel(k: 3);

            // 训练模型
            model.Train(data, labels);

            // 预测
            double[] testFeatures = { 1.0, 2.0 };
            double predictedValue = model.Predict(testFeatures);

            System.Console.WriteLine("预测值: " + predictedValue);
        }
    }
}
